home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Online / opennap / handler.c < prev    next >
C/C++ Source or Header  |  2001-06-08  |  27KB  |  699 lines

  1. /* Copyright (C) 2000-1 drscholl@users.sourceforge.net
  2.    This is free software distributed under the terms of the
  3.    GNU Public License.  See the file COPYING for details.
  4.  
  5.    $Id: handler.c,v 1.112 2001/02/15 08:39:45 drscholl Exp $ */
  6.  
  7. #include <string.h>
  8. #include <errno.h>
  9. #include <stdlib.h>
  10. #ifndef WIN32
  11. #include <unistd.h>
  12. #endif
  13. #include "opennap.h"
  14. #include "debug.h"
  15. #if DEBUG
  16. #include <ctype.h>
  17. #endif
  18.  
  19. static  HANDLER (histogram);
  20.  
  21. /* 214 */
  22. HANDLER (server_stats)
  23. {
  24.     (void) pkt;
  25.     (void) len;
  26.     (void) tag;
  27.     send_cmd (con, MSG_SERVER_STATS, "%d %d %d", Users->dbsize, Num_Files,
  28.               (int) (Num_Gigs / 1048576.));
  29. }
  30.  
  31. /* 10018 :<server> <target> <packet>
  32.    allows a server to send an arbitrary message to a remote user */
  33. HANDLER (encapsulated)
  34. {
  35.     char   *nick, ch, *ptr;
  36.     USER   *user;
  37.  
  38.     (void) tag;
  39.     ASSERT (validate_connection (con));
  40.     CHECK_SERVER_CLASS ("encapsulated");
  41.     if (*pkt != ':')
  42.     {
  43.         log ("encapsulated: server message does not begin with a colon (:)");
  44.         return;
  45.     }
  46.     nick = strchr (pkt + 1, ' ');
  47.     if (!nick)
  48.     {
  49.         log ("encapsulated: missing target nick");
  50.         return;
  51.     }
  52.     nick++;
  53.     ptr = strchr (nick, ' ');
  54.     if (!ptr)
  55.     {
  56.         log ("encapsulated: missing encapsulated packet");
  57.         return;
  58.     }
  59.     ch = *ptr;
  60.     *ptr = 0;
  61.     user = hash_lookup (Users, nick);
  62.     if (!user)
  63.     {
  64.         log ("encapsulated: no such user %s", nick);
  65.         return;
  66.     }
  67.     if (user->local)
  68.     {
  69.         ptr++;
  70.         queue_data (user->con, ptr, len - (ptr - pkt));
  71.     }
  72.     else
  73.     {
  74.         *ptr = ch;
  75.         /* avoid copying the data twice by peeking into the send buffer to
  76.            grab the message header and body together */
  77.         pass_message (con, con->recvbuf->data + con->recvbuf->consumed,
  78.                       4 + len);
  79.     }
  80. }
  81.  
  82. /* the windows napster client will hang indefinitely waiting for this, so
  83.  * return what it expects.
  84.  */
  85. static HANDLER (version_check)
  86. {
  87.     (void) pkt;
  88.     (void) tag;
  89.     (void) len;
  90.     if (ISUSER (con))
  91.         send_cmd (con, MSG_CLIENT_VERSION_CHECK, "");
  92. }
  93.  
  94. /* certain user commands need to be exempt from flood control or the server
  95.  * won't work correctly.
  96.  */
  97. #define F_EXEMPT                1       /* exempt from flood control */
  98.  
  99. typedef struct
  100. {
  101.     unsigned int message;
  102.             HANDLER ((*handler));
  103.     unsigned int flags;
  104.     unsigned long count;
  105.     double  bytes;
  106. }
  107. HANDLER;
  108.  
  109. #define NORMAL(a,b) {a,b,0,0,0}
  110. #define EXEMPT(a,b) {a,b,F_EXEMPT,0,0}
  111.  
  112. /* this is the table of valid commands we accept from both users and servers
  113.    THIS TABLE MUST BE SORTED BY MESSAGE TYPE */
  114. static HANDLER Protocol[] = {
  115.     NORMAL (MSG_SERVER_ERROR, server_error),    /* 0 */
  116.     NORMAL (MSG_CLIENT_LOGIN, login),   /* 2 */
  117.     NORMAL (MSG_CLIENT_VERSION_CHECK, version_check),   /* 4 */
  118.     NORMAL (MSG_CLIENT_LOGIN_REGISTER, login),  /* 6 */
  119.     NORMAL (MSG_CLIENT_REGISTER, register_nick),        /* 7 */
  120.     NORMAL (MSG_CLIENT_CHECK_PASS, check_password),     /* 11 */
  121.     NORMAL (MSG_CLIENT_REGISTRATION_INFO, ignore_command),      /* 14 */
  122. #ifndef ROUTING_ONLY
  123.     EXEMPT (MSG_CLIENT_ADD_FILE, add_file),     /* 100 */
  124.     EXEMPT (MSG_CLIENT_REMOVE_FILE, remove_file),       /* 102 */
  125. #endif
  126.     NORMAL (MSG_CLIENT_UNSHARE_ALL, unshare_all),       /* 110 */
  127. #ifndef ROUTING_ONLY
  128.     NORMAL (MSG_CLIENT_SEARCH, search), /* 200 */
  129. #endif
  130.     NORMAL (MSG_CLIENT_DOWNLOAD, download),     /* 203 */
  131.     NORMAL (MSG_CLIENT_PRIVMSG, privmsg),       /* 205 */
  132.     EXEMPT (MSG_CLIENT_ADD_HOTLIST, add_hotlist),       /* 207 */
  133.     EXEMPT (MSG_CLIENT_ADD_HOTLIST_SEQ, add_hotlist),   /* 208 */
  134.     NORMAL (MSG_CLIENT_BROWSE, browse), /* 211 */
  135.     NORMAL (MSG_SERVER_STATS, server_stats),    /* 214 */
  136.     NORMAL (MSG_CLIENT_RESUME_REQUEST, resume), /* 215 */
  137.     NORMAL (MSG_CLIENT_DOWNLOAD_START, download_start), /* 218 */
  138.     NORMAL (MSG_CLIENT_DOWNLOAD_END, download_end),     /* 219 */
  139.     NORMAL (MSG_CLIENT_UPLOAD_START, upload_start),     /* 220 */
  140.     NORMAL (MSG_CLIENT_UPLOAD_END, upload_end), /* 221 */
  141.     NORMAL (MSG_CLIENT_CHECK_PORT, ignore_command),     /* 300 */
  142.     NORMAL (MSG_CLIENT_REMOVE_HOTLIST, remove_hotlist), /* 303 */
  143.     NORMAL (MSG_CLIENT_IGNORE_LIST, ignore_list),       /* 320 */
  144.     NORMAL (MSG_CLIENT_IGNORE_USER, ignore),    /* 322 */
  145.     NORMAL (MSG_CLIENT_UNIGNORE_USER, unignore),        /* 323 */
  146.     NORMAL (MSG_CLIENT_CLEAR_IGNORE, clear_ignore),     /* 326 */
  147.     NORMAL (MSG_CLIENT_JOIN, join),     /* 400 */
  148.     NORMAL (MSG_CLIENT_PART, part),     /* 401 */
  149.     NORMAL (MSG_CLIENT_PUBLIC, public), /* 402 */
  150.     NORMAL (MSG_SERVER_PUBLIC, public), /* 403 */
  151.     NORMAL (MSG_SERVER_NOSUCH, server_error),   /* 404 */
  152.     NORMAL (MSG_SERVER_TOPIC, topic),   /* 410 */
  153.     NORMAL (MSG_CLIENT_CHANNEL_BAN_LIST, channel_banlist),      /* 420 */
  154.     NORMAL (MSG_CLIENT_CHANNEL_BAN, channel_ban),       /* 422 */
  155.     NORMAL (MSG_CLIENT_CHANNEL_UNBAN, channel_ban),     /* 423 */
  156.     NORMAL (MSG_CLIENT_CHANNEL_CLEAR_BANS, channel_clear_bans), /* 424 */
  157.     NORMAL (MSG_CLIENT_DOWNLOAD_FIREWALL, download),    /* 500 */
  158.     NORMAL (MSG_CLIENT_USERSPEED, user_speed),  /* 600 */
  159.     NORMAL (MSG_CLIENT_WHOIS, whois),   /* 603 */
  160.     NORMAL (MSG_CLIENT_SETUSERLEVEL, level),    /* 606 */
  161.     NORMAL (MSG_SERVER_UPLOAD_REQUEST, upload_request), /* 607 */
  162.     NORMAL (MSG_CLIENT_UPLOAD_OK, upload_ok),   /* 608 */
  163.     NORMAL (MSG_CLIENT_KILL, kill_user),        /* 610 */
  164.     NORMAL (MSG_CLIENT_NUKE, nuke),     /* 611 */
  165.     NORMAL (MSG_CLIENT_BAN, ban),       /* 612 */
  166.     NORMAL (MSG_CLIENT_ALTER_PORT, alter_port), /* 613 */
  167.     NORMAL (MSG_CLIENT_UNBAN, unban),   /* 614 */
  168.     NORMAL (MSG_CLIENT_BANLIST, banlist),       /* 615 */
  169.     NORMAL (MSG_CLIENT_LIST_CHANNELS, list_channels),   /* 618 */
  170.     NORMAL (MSG_CLIENT_LIMIT, queue_limit),     /* 619 */
  171.     NORMAL (MSG_CLIENT_MOTD, show_motd),        /* 621 */
  172.     NORMAL (MSG_CLIENT_MUZZLE, muzzle), /* 622 */
  173.     NORMAL (MSG_CLIENT_UNMUZZLE, muzzle),       /* 623 */
  174.     NORMAL (MSG_CLIENT_ALTER_SPEED, alter_speed),       /* 625 */
  175.     NORMAL (MSG_CLIENT_DATA_PORT_ERROR, data_port_error),       /* 626 */
  176.     NORMAL (MSG_CLIENT_WALLOP, wallop), /* 627 */
  177.     NORMAL (MSG_CLIENT_ANNOUNCE, announce),     /* 628 */
  178.     NORMAL (MSG_CLIENT_BROWSE_DIRECT, browse_direct),   /* 640 */
  179.     NORMAL (MSG_SERVER_BROWSE_DIRECT_OK, browse_direct_ok),     /* 641 */
  180.     NORMAL (MSG_CLIENT_CLOAK, cloak),   /* 652 */
  181.     NORMAL (MSG_CLIENT_CHANGE_SPEED, change_speed),     /* 700 */
  182.     NORMAL (MSG_CLIENT_CHANGE_PASS, change_pass),       /* 701 */
  183.     NORMAL (MSG_CLIENT_CHANGE_EMAIL, change_email),     /* 702 */
  184.     NORMAL (MSG_CLIENT_CHANGE_DATA_PORT, change_data_port),     /* 703 */
  185.     NORMAL (MSG_CLIENT_PING_SERVER, ping_server),       /* 750 */
  186.     NORMAL (MSG_CLIENT_PING, ping),     /* 751 */
  187.     NORMAL (MSG_CLIENT_PONG, ping),     /* 752 */
  188.     NORMAL (MSG_CLIENT_ALTER_PASS, alter_pass), /* 753 */
  189.     NORMAL (MSG_CLIENT_SERVER_RECONFIG, server_reconfig),       /* 800 */
  190.     NORMAL (MSG_CLIENT_SERVER_VERSION, server_version), /* 801 */
  191.     NORMAL (MSG_CLIENT_SERVER_CONFIG, server_config),   /* 810 */
  192.     NORMAL (MSG_CLIENT_CLEAR_CHANNEL, clear_channel),   /* 820 */
  193.     NORMAL (MSG_CLIENT_REDIRECT, redirect_client),      /* 821 */
  194.     NORMAL (MSG_CLIENT_CYCLE, cycle_client),    /* 822 */
  195.     NORMAL (MSG_CLIENT_SET_CHAN_LEVEL, channel_level),  /* 823 */
  196.     NORMAL (MSG_CLIENT_EMOTE, emote),   /* 824 */
  197.     NORMAL (MSG_CLIENT_CHANNEL_LIMIT, channel_limit),   /* 826 */
  198.     NORMAL (MSG_CLIENT_FULL_CHANNEL_LIST, full_channel_list),   /* 827 */
  199.     NORMAL (MSG_CLIENT_KICK, kick),     /* 829 */
  200.     NORMAL (MSG_CLIENT_NAMES_LIST, list_users), /* 830 */
  201.     NORMAL (MSG_CLIENT_GLOBAL_USER_LIST, global_user_list),     /* 831 */
  202. #ifndef ROUTING_ONLY
  203.     EXEMPT (MSG_CLIENT_ADD_DIRECTORY, add_directory),   /* 870 */
  204. #endif
  205.     NORMAL (920, ignore_command),       /* 920 */
  206.  
  207.     /* non-standard messages */
  208.     NORMAL (MSG_CLIENT_QUIT, client_quit),      /* 10000 */
  209.     NORMAL (MSG_SERVER_LOGIN, server_login),    /* 10010 */
  210.     NORMAL (MSG_SERVER_LOGIN_ACK, server_login_ack),    /* 10011 */
  211.     NORMAL (MSG_SERVER_USER_SHARING, user_sharing),     /* 10012 */
  212.     NORMAL (MSG_SERVER_REGINFO, reginfo),       /* 10014 */
  213.     NORMAL (MSG_SERVER_REMOTE_SEARCH, remote_search),   /* 10015 */
  214.     NORMAL (MSG_SERVER_REMOTE_SEARCH_RESULT, remote_search_result),     /* 10016 */
  215.     NORMAL (MSG_SERVER_REMOTE_SEARCH_END, remote_search_end),   /* 10017 */
  216.     NORMAL (MSG_SERVER_ENCAPSULATED, encapsulated),     /* 10018 */
  217.     NORMAL (MSG_SERVER_LINK_INFO, link_info),   /* 10019 */
  218.     NORMAL (MSG_SERVER_QUIT, server_disconnect),        /* 10020 - deprecated by 10101 */
  219.     NORMAL (MSG_SERVER_NOTIFY_MODS, remote_notify_mods),        /* 10021 */
  220.     NORMAL (MSG_SERVER_SERVER_PONG, server_pong),       /* 10022 */
  221.     NORMAL (MSG_SERVER_TIME_CHECK, time_check), /* 10023 */
  222.     NORMAL (MSG_SERVER_WHOIS_NOTIFY, whois_notify),     /* 10024 */
  223.     NORMAL (MSG_CLIENT_CONNECT, server_connect),        /* 10100 */
  224.     NORMAL (MSG_CLIENT_DISCONNECT, server_disconnect),  /* 10101 */
  225.     NORMAL (MSG_CLIENT_KILL_SERVER, kill_server),       /* 10110 */
  226.     NORMAL (MSG_CLIENT_REMOVE_SERVER, remove_server),   /* 10111 */
  227.     NORMAL (MSG_CLIENT_LINKS, server_links),    /* 10112 */
  228.     NORMAL (MSG_CLIENT_USAGE_STATS, server_usage),      /* 10115 */
  229.     NORMAL (MSG_CLIENT_REHASH, rehash), /* 10116 */
  230.     NORMAL (MSG_CLIENT_VERSION_STATS, client_version_stats),    /* 10118 */
  231.     NORMAL (MSG_CLIENT_WHICH_SERVER, which_server),     /* 10119 */
  232.     NORMAL (MSG_CLIENT_PING_ALL_SERVERS, ping_all_servers),     /* 10120 */
  233.     NORMAL (MSG_CLIENT_WHO_WAS, who_was),       /* 10121 */
  234.     NORMAL (MSG_CLIENT_MASS_KILL, mass_kill),   /* 10122 */
  235.     NORMAL (MSG_CLIENT_HISTOGRAM, histogram),   /* 10123 */
  236.     NORMAL (MSG_CLIENT_REGISTER_USER, register_user),   /* 10200 */
  237.     NORMAL (MSG_CLIENT_USER_MODE, user_mode_cmd),       /* 10203 */
  238.     NORMAL (MSG_CLIENT_OP, channel_op), /* 10204 */
  239.     NORMAL (MSG_CLIENT_DEOP, channel_op),       /* 10205 */
  240.     NORMAL (MSG_CLIENT_CHANNEL_WALLOP, channel_wallop), /* 10208 */
  241.     NORMAL (MSG_CLIENT_CHANNEL_MODE, channel_mode),     /* 10209 */
  242.     NORMAL (MSG_CLIENT_CHANNEL_INVITE, channel_invite), /* 10210 */
  243.     NORMAL (MSG_CLIENT_CHANNEL_VOICE, channel_op),      /* 10211 */
  244.     NORMAL (MSG_CLIENT_CHANNEL_UNVOICE, channel_op),    /* 10212 */
  245.     NORMAL (MSG_CLIENT_CHANNEL_MUZZLE, channel_muzzle), /* 10213 */
  246.     NORMAL (MSG_CLIENT_CHANNEL_UNMUZZLE, channel_muzzle),       /* 10214 */
  247.     NORMAL (MSG_CLIENT_CLASS_ADD, generic_acl_add), /* 10250 */
  248.     NORMAL (MSG_CLIENT_CLASS_DEL, generic_acl_del), /* 10251 */
  249.     NORMAL (MSG_CLIENT_CLASS_LIST, generic_acl_list), /* 10252 */
  250.     NORMAL (MSG_CLIENT_DLINE_ADD, generic_acl_add),
  251.     NORMAL (MSG_CLIENT_DLINE_DEL, generic_acl_del),
  252.     NORMAL (MSG_CLIENT_DLINE_LIST, generic_acl_list),
  253.     NORMAL (MSG_CLIENT_ILINE_ADD, generic_acl_add),
  254.     NORMAL (MSG_CLIENT_ILINE_DEL, generic_acl_del),
  255.     NORMAL (MSG_CLIENT_ILINE_LIST, generic_acl_list),
  256.     NORMAL (MSG_CLIENT_ELINE_ADD, generic_acl_add),
  257.     NORMAL (MSG_CLIENT_ELINE_DEL, generic_acl_del),
  258.     NORMAL (MSG_CLIENT_ELINE_LIST, generic_acl_list),
  259.  
  260. #ifndef ROUTING_ONLY
  261.     EXEMPT (MSG_CLIENT_SHARE_FILE, share_file), /* 10300 */
  262. #endif
  263. #if 0
  264.     NORMAL (MSG_CLIENT_BROWSE_NEW, browse_new), /* 10301 */
  265. #endif
  266. };
  267. static int Protocol_Size = sizeof (Protocol) / sizeof (HANDLER);
  268.  
  269. /* dummy entry used to keep track of invalid commands */
  270. static HANDLER unknown_numeric = { 0, 0, 0, 0, 0 };
  271.  
  272. /* 10123
  273.  * report statistics for server commands.
  274.  */
  275. static HANDLER (histogram)
  276. {
  277.     unsigned long  count = 0;
  278.     double  bytes = 0;
  279.     int     l;
  280.  
  281.     (void) pkt;
  282.     (void) len;
  283.     CHECK_USER_CLASS ("histogram");
  284.     if (con->user->level < LEVEL_ELITE)
  285.     {
  286.         permission_denied (con);
  287.         return;
  288.     }
  289.     for (l = 0; l < Protocol_Size; l++)
  290.     {
  291.         send_cmd (con, tag, "%d %u %.0f", Protocol[l].message,
  292.                   Protocol[l].count, Protocol[l].bytes);
  293.         count += Protocol[l].count;
  294.         bytes += Protocol[l].bytes;
  295.     }
  296.     send_cmd (con, MSG_SERVER_HISTOGRAM, "%d %u %.0f %lu %.0f",
  297.               unknown_numeric.message, unknown_numeric.count,
  298.               unknown_numeric.bytes, count, bytes);
  299. }
  300.  
  301. /* use a binary search to find the table in the entry */
  302. static int
  303. find_handler (unsigned int tag)
  304. {
  305.     int     min = 0, max = Protocol_Size - 1, try;
  306.  
  307.     while (!SigCaught)
  308.     {
  309.         try = (max + min) / 2;
  310.         if (tag == Protocol[try].message)
  311.             return try;
  312.         else if (min == max)
  313.             return -1;          /* not found */
  314.         else if (tag < Protocol[try].message)
  315.         {
  316.             if (try == min)
  317.                 return -1;
  318.             max = try - 1;
  319.         }
  320.         else
  321.         {
  322.             if (try == max)
  323.                 return -1;
  324.             min = try + 1;
  325.         }
  326.         ASSERT (min <= max);
  327.     }
  328.     return -1;
  329. }
  330.  
  331. /* this is not a real handler, but takes the same arguments as one */
  332. HANDLER (dispatch_command)
  333. {
  334.     int     l;
  335.     u_char  byte;
  336.  
  337.     ASSERT (validate_connection (con));
  338.     ASSERT (pkt != 0);
  339.  
  340.     /* HACK ALERT
  341.        the handler routines all assume that the `pkt' argument is nul (\0)
  342.        terminated, so we have to replace the byte after the last byte in
  343.        this packet with a \0 to make sure we dont read overflow in the
  344.        handlers.  the handle_connection() function should always allocate 1
  345.        byte more than necessary for this purpose */
  346.     ASSERT (VALID_LEN
  347.             (con->recvbuf->data, con->recvbuf->consumed + 4 + len + 1));
  348.     byte = *(pkt + len);
  349.     *(pkt + len) = 0;
  350.     l = find_handler (tag);
  351.     if (l != -1)
  352.     {
  353.         ASSERT (Protocol[l].handler != 0);
  354.  
  355.         /* do flood control if enabled */
  356.         if (Flood_Time > 0 && !(Protocol[l].flags & F_EXEMPT) && ISUSER (con))
  357.         {
  358.             /* this command is subject to flood control. */
  359.             if (con->flood_start + Flood_Time < global.current_time)
  360.             {
  361.                 /* flood expired, reset counters */
  362.                 con->flood_start = global.current_time;
  363.                 con->flood_commands = 0;
  364.             }
  365.             else if (++con->flood_commands >= Flood_Commands)
  366.             {
  367.                 LIST   *list;
  368.  
  369.                 log
  370.                     ("dispatch_command: flooding from %s!%s (numeric = %hu)",
  371.                      con->user->nick, con->host, tag);
  372.                 notify_mods (FLOODLOG_MODE,
  373.                              "Flooding from %s!%s (numeric = %hu)",
  374.                              con->user->nick, con->host, tag);
  375.                 /* stop reading from the descriptor until the flood counter
  376.                  * expires.
  377.                  */
  378.                 clear_read (con->fd);
  379.  
  380.                 /* add to the list of flooders that is check in the main
  381.                  * loop.  Since we don't traverse the entire client list we
  382.                  * have to keep track of which ones to check for expiration
  383.                  */
  384.                 list = CALLOC (1, sizeof (LIST));
  385.                 list->data = con;
  386.                 Flooders = list_push (Flooders, list);
  387.             }
  388.         }
  389.  
  390.         /* note that we pass only the data part of the packet */
  391.         Protocol[l].handler (con, tag, len, pkt);
  392.         Protocol[l].count++;
  393.         Protocol[l].bytes += len;
  394.         goto done;
  395.     }
  396.     log ("dispatch_command: unknown message: tag=%hu, length=%hu, data=%s",
  397.          tag, len, pkt);
  398.     unknown_numeric.message = tag;
  399.     unknown_numeric.count++;
  400.     unknown_numeric.bytes += len;
  401.  
  402.     send_cmd (con, MSG_SERVER_NOSUCH, "Unknown command code %hu", tag);
  403. #if DEBUG
  404.     /* if this is a server connection, shut it down to avoid flooding the
  405.        other server with these messages */
  406.     if (ISSERVER (con))
  407.     {
  408.         u_char  ch;
  409.         int     bytes;
  410.  
  411.         /* dump some bytes from the input buffer to see if it helps aid
  412.            debugging */
  413.         bytes = con->recvbuf->datasize - con->recvbuf->consumed;
  414.         /* print at most 128 bytes */
  415.         if (bytes > 128)
  416.             bytes = 128;
  417.         fprintf (stdout, "Dump(%d): ",
  418.                  con->recvbuf->datasize - con->recvbuf->consumed);
  419.         for (l = con->recvbuf->consumed; bytes > 0; bytes--, l++)
  420.         {
  421.             ch = *(con->recvbuf->data + l);
  422.             fputc (isprint (ch) ? ch : '.', stdout);
  423.         }
  424.         fputc ('\n', stdout);
  425.     }
  426. #endif /* DEBUG */
  427.   done:
  428.     /* restore the byte we overwrite at the beginning of this function */
  429.     *(pkt + len) = byte;
  430. }
  431.  
  432. void
  433. handle_connection (CONNECTION * con)
  434. {
  435.     int     n;
  436.     u_short tag, len;
  437.  
  438.     ASSERT (validate_connection (con));
  439.  
  440.     if (ISSERVER (con))
  441.     {
  442.         /* server data is compressed.  read as much as we can and pass it
  443.            to the decompressor.  we attempt to read all data from the socket
  444.            in this loop, which will prevent unnecessary passes through the
  445.            main loop (since select would return immediately) */
  446.         do
  447.         {
  448.             n = READ (con->fd, Buf, sizeof (Buf));
  449.             if (n <= 0)
  450.             {
  451.                 if (n == -1)
  452.                 {
  453.                     /* try to empty the socket each time, so we read until
  454.                      * we hit this error (queue empty).  this should only
  455.                      * happen in the rare event that the data in the queue
  456.                      * is a multiple of sizeof(Buf)
  457.                      */
  458.                     if (N_ERRNO == EWOULDBLOCK)
  459.                         break;  /* not an error */
  460.                     log
  461.                         ("handle_connection: read: %s (errno %d) for host %s (fd %d)",
  462.                          strerror (N_ERRNO), N_ERRNO, con->host, con->fd);
  463.                 }
  464.                 else
  465.                     log ("handle_connection: EOF from %s", con->host);
  466.                 destroy_connection (con);
  467.                 return;
  468.             }
  469.  
  470.             if (global.min_read > 0 && n < global.min_read)
  471.             {
  472.                 log ("handle_connection: %d bytes from %s", n,
  473.                         con->host);
  474.             }
  475.  
  476.             global.bytes_in += n;
  477.             /* this can safely be called multiple times in this loop.  the
  478.              * decompressor will realloc the output buffer if there is not
  479.              * enough room to store everything
  480.              */
  481.             if (buffer_decompress (con->recvbuf, con->sopt->zin, Buf, n))
  482.             {
  483.                 destroy_connection (con);
  484.                 return;
  485.             }
  486.             /* if what we read was equal to sizeof(Buf) it's very likely
  487.              * that more data exists in the queue
  488.              */
  489.         }
  490.         while (n == sizeof (Buf));
  491.     }
  492.     else
  493.     {
  494.         /* create the input buffer if it doesn't yet exist */
  495.         if (!con->recvbuf)
  496.         {
  497.             con->recvbuf = CALLOC (1, sizeof (BUFFER));
  498.             if (!con->recvbuf)
  499.             {
  500.                 OUTOFMEMORY ("handle_connection");
  501.                 destroy_connection (con);
  502.                 return;
  503.             }
  504. #if DEBUG
  505.             con->recvbuf->magic = MAGIC_BUFFER;
  506. #endif
  507.             con->recvbuf->data = MALLOC (5);
  508.             if (!con->recvbuf->data)
  509.             {
  510.                 OUTOFMEMORY ("handle_connection");
  511.                 destroy_connection (con);
  512.                 return;
  513.             }
  514.             con->recvbuf->datamax = 4;
  515.         }
  516.         /* read the packet header if we haven't seen it already */
  517.         while (con->recvbuf->datasize < 4)
  518.         {
  519.             n = READ (con->fd, con->recvbuf->data + con->recvbuf->datasize,
  520.                       4 - con->recvbuf->datasize);
  521.             if (n == -1)
  522.             {
  523.                 if (N_ERRNO != EWOULDBLOCK)
  524.                 {
  525.                     log
  526.                         ("handle_connection: read: %s (errno %d) for host %s",
  527.                          strerror (N_ERRNO), N_ERRNO, con->host);
  528.                     destroy_connection (con);
  529.                 }
  530.                 return;
  531.             }
  532.             else if (n == 0)
  533.             {
  534.                 destroy_connection (con);
  535.                 return;
  536.             }
  537.             global.bytes_in += n;
  538.             con->recvbuf->datasize += n;
  539.         }
  540.         /* read the packet body */
  541.         memcpy (&len, con->recvbuf->data, 2);
  542.         len = BSWAP16 (len);
  543.         if (len > 0)
  544.         {
  545.             if (len > Max_Command_Length)
  546.             {
  547.                 log ("handle_connection: %hu byte message from %s",
  548.                      len, con->host);
  549.                 destroy_connection (con);
  550.                 return;
  551.             }
  552.  
  553.             /* if there isn't enough space to read the entire body, resize the
  554.                input buffer */
  555.             if (con->recvbuf->datamax < 4 + len)
  556.             {
  557.                 /* allocate 1 extra byte for the \0 that dispatch_command()
  558.                    requires */
  559.                 if (safe_realloc ((void **) &con->recvbuf->data, 4 + len + 1))
  560.                 {
  561.                     OUTOFMEMORY ("handle_connection");
  562.                     destroy_connection (con);
  563.                     return;
  564.                 }
  565.                 con->recvbuf->datamax = 4 + len;
  566.             }
  567.             n = READ (con->fd, con->recvbuf->data + con->recvbuf->datasize,
  568.                       len + 4 - con->recvbuf->datasize);
  569.             if (n == -1)
  570.             {
  571.                 /* since the header and body could arrive in separate packets,
  572.                    we have to check for this here so we don't close the
  573.                    connection on this nonfatal error.  we just wait for the
  574.                    next packet to arrive */
  575.                 if (N_ERRNO != EWOULDBLOCK)
  576.                 {
  577.                     log
  578.                         ("handle_connection: read: %s (errno %d) for host %s",
  579.                          strerror (N_ERRNO), N_ERRNO, con->host);
  580.                     destroy_connection (con);
  581.                 }
  582.                 return;
  583.             }
  584.             else if (n == 0)
  585.             {
  586.                 log ("handle_connection: EOF from %s", con->host);
  587.                 destroy_connection (con);
  588.                 return;
  589.             }
  590.             con->recvbuf->datasize += n;
  591.             global.bytes_in += n;
  592.         }
  593.     }
  594.     /* process as many complete commands as possible.  for a client this
  595.        will be exactly one, but a server link may have sent multiple commands
  596.        in one compressed packet */
  597.     while (con->recvbuf->consumed < con->recvbuf->datasize)
  598.     {
  599.         /* if we don't have the complete packet header, wait until we
  600.            read more data */
  601.  
  602.         if (con->recvbuf->datasize - con->recvbuf->consumed < 4)
  603.             break;
  604.  
  605.         /* read the packet header */
  606.         memcpy (&len, con->recvbuf->data + con->recvbuf->consumed, 2);
  607.         memcpy (&tag, con->recvbuf->data + con->recvbuf->consumed + 2, 2);
  608.  
  609.         len = BSWAP16 (len);
  610.         tag = BSWAP16 (tag);
  611.  
  612.         /* check if the entire packet body has arrived */
  613.         if (con->recvbuf->consumed + 4 + len > con->recvbuf->datasize)
  614.             break;
  615.         /* require that the client register before doing anything else */
  616.         if (con->class == CLASS_UNKNOWN &&
  617.             (tag != MSG_CLIENT_LOGIN && tag != MSG_CLIENT_LOGIN_REGISTER &&
  618.              tag != MSG_CLIENT_REGISTER && tag != MSG_SERVER_LOGIN &&
  619.              tag != MSG_SERVER_LOGIN_ACK && tag != MSG_SERVER_ERROR &&
  620.              tag != 4 &&        /* unknown: v2.0 beta 5a sends this? */
  621.              tag != 300 && tag != 11 && tag != 920))
  622.         {
  623.             log ("handle_connection: %s is not registered", con->host);
  624.             *(con->recvbuf->data + con->recvbuf->consumed + 4 + len) = 0;
  625.             log ("handle_connection: tag=%hu, len=%hu, data=%s", tag, len,
  626.                  con->recvbuf->data + con->recvbuf->consumed + 4);
  627.  
  628. #if 0
  629.             /* not sure why the official servers do this, but lets
  630.              * be compatible.
  631.              */
  632.             send_cmd (con, MSG_SERVER_ECHO, "%hu: %s", tag,
  633.                       con->recvbuf->data + con->recvbuf->consumed + 4);
  634.  
  635.             con->recvbuf->consumed += 4 + len;
  636.             break;
  637. #else
  638.             send_cmd (con, MSG_SERVER_ERROR, "invalid command");
  639.             destroy_connection (con);
  640.             return;
  641. #endif
  642.         }
  643.  
  644.         if (Servers && ISUSER (con))
  645.         {
  646.             /* check for end of share/unshare sequence.  in order to avoid
  647.                having to send a single message for each shared file,
  648.                the add_file and remove_file commands set a flag noting the
  649.                start of a possible series of commands.  this routine checks
  650.                to see if the end of the sequence has been reached (a command
  651.                other than share/unshare has been issued) and then relays
  652.                the final result to the peer servers.
  653.                NOTE: the only issue with this is that if the user doesn't
  654.                issue any commands after sharing files, the information will
  655.                never get passed to the peer servers.  This is probably ok
  656.                since this case will seldom happen */
  657.             if (con->user->sharing)
  658.             {
  659.                 if (tag != MSG_CLIENT_ADD_FILE
  660.                     && tag != MSG_CLIENT_SHARE_FILE
  661.                     && tag != MSG_CLIENT_ADD_DIRECTORY)
  662.                 {
  663.                     pass_message_args (con, MSG_SERVER_USER_SHARING,
  664.                                        "%s %hu %u", con->user->nick,
  665.                                        con->user->shared, con->user->libsize);
  666.                     con->user->sharing = 0;
  667.                 }
  668.             }
  669.             else if (con->user->unsharing)
  670.             {
  671.                 if (tag != MSG_CLIENT_REMOVE_FILE)
  672.                 {
  673.                     pass_message_args (con, MSG_SERVER_USER_SHARING,
  674.                                        "%s %hu %u", con->user->nick,
  675.                                        con->user->shared, con->user->libsize);
  676.                     con->user->unsharing = 0;
  677.                 }
  678.             }
  679.         }
  680.         /* call the protocol handler */
  681.         dispatch_command (con, tag, len,
  682.                           con->recvbuf->data + con->recvbuf->consumed + 4);
  683.         /* mark data as processed */
  684.         con->recvbuf->consumed += 4 + len;
  685.     }
  686.     if (con->recvbuf->consumed)
  687.     {
  688.         n = con->recvbuf->datasize - con->recvbuf->consumed;
  689.         if (n > 0)
  690.         {
  691.             /* shift down unprocessed data */
  692.             memmove (con->recvbuf->data,
  693.                      con->recvbuf->data + con->recvbuf->consumed, n);
  694.         }
  695.         con->recvbuf->datasize = n;
  696.         con->recvbuf->consumed = 0;     /* reset */
  697.     }
  698. }
  699.